iT邦幫忙

2023 iThome 鐵人賽

DAY 6
0

所有權(Ownership), 參考(References) and 借用(Borrowing)

所有權(Ownership)

Rust 的所有權 (Ownership) 概念是Rust核心的一部分,它使Rust能在沒有垃圾收集器的情況下進行記憶體管理,並確保記憶體安全。

Rust 的所有權系統主要基於三個規則:

  • Rust 中每個數值都有個擁有者(owner)。
  • 同時間只能有一個擁有者。
  • 當擁有者離開作用域時,數值就會被丟棄。

變數作用域

 {                      // s 在此處無效,因為它還沒宣告
    let s = "hello";   // s 在此開始視為有效
    // 使用 s
 }                      // 此作用域結束, s 不再有效
let s1 = String::from("hello");
let s2 = s1;

println!("{}, world!", s1);

這一段程式碼會報錯,String::from 會建立一個String值並將所有權賦予s1,當 s2 被賦予 s1 時,s1 的所有權將被轉移給 s2。此時,s1 不再引用任何值,因此會被銷毀。
這種情況可以用clone,以python來說就是deep copy

let s1 = String::from("hello");
let s2 = s1.clone();

println!("s1 = {}, s2 = {}", s1, s2);  // 沒問題!

let s1 = "hello";
let s2 = s1;

println!("{}, world!", s1);

這段程式碼不會報錯,s1 是字面值。字面值是一種在編譯時就被確定的值,"hello" 會在編譯時被轉換為一個 String 值。這個 String 值是不可變的,因此它可以被多次借用。當 s2 被賦予 s1 時,s1 仍然引用該 String 值,因此不會被銷毀。

參考(References) and 借用(Borrowing)

Rust 通常避免複製數據,而是使用「參考」或「借用」。這可以提高效能並確保記憶體安全性。
建立參考(References)的行為稱為借用(Borrowing)

不可變參考

fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1);
    println!("'{}' 的長度是 {}。", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

在上面的程式中,calculate_length 函數不擁有 s1 的所有權,只是借用它。因此,當 calculate_length 函數返回後,s1 仍然是 main 函數的,且可以繼續使用。

可變參考

fn main() {
    let mut s1 = String::from("hello");
    change(&mut s1);
    println!("{}", s1);
}

fn change(s: &mut String) {
    s.push_str(", world");
}

在上面的code中,s1 是可變的,並被傳遞給 change 函數作為一個可變引用,所以 change 函數可以修改 s1 的內容。

注意,Rust 在特定範圍內只允許一次可變借用,這是為了在編譯時防止資料競爭(data races)。但你可以有多個不可變的借用,因為它們不會修改數據。

資料競爭(data races)引發情況:

  • 同時有兩個以上的指標存取同個資料。
  • 至少有一個指標在寫入資料。
  • 沒有針對資料的同步存取機制。

上一篇
[Day 5] Rust 學習計畫2
下一篇
[Day 7] ECS是什麼?能吃嗎?
系列文
三十歲時在做什麼?有沒有空?可以來做遊戲嗎?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言